//
//  STCommodityMobileViewModel.swift
//  StarTimesON
//
//  Created by Toj on 8/19/22.
//  Copyright © 2022 StarTimes. All rights reserved.
//

import UIKit
import STToolsModule

class STCommodityMobileViewModel: NSObject {
    // 当前选中的商品, 但是不是最终选中的商品, 可能存在逻辑被替换, 只做一个参考
    public var selectedProduct: MemberProductDto?
    // 从All 请求回来的流量包
    var dataBundleInfo: DataBundleInfo?
    
    private let ds_categroy = "MembershipListActivity"
    
    var isFromCoupons = false
    
    // 选中的规格
    public var selectedCommodity: MemberCommodityDto? { willSet {
        selectedCommodity?.isSelected = false
        newValue?.isSelected = true
        
        tipsSection?.commodityTips?.setTipsModel(commodity: newValue)
        tipsSection?.cellSize = tipsSection?.commodityTips?.tipsSize ?? CGSize(width: STScreenWidth, height: 0.1)
        let bottom = tipsSection?.commodityTips?.bottomMargin ?? 12
        tipsSection?.layoutEdgeinset = UIEdgeInsets(top: 8, left: lr, bottom: bottom, right: lr)
    } didSet {
        guard let commodity = selectedCommodity else { return }
        let commodityID = String(commodity.id)
        // 选择过的商品是否有优惠券
        hadCoupon = hadCoupon || (commodity.coupon != nil)
        let channelModel = commodityChannelDict[commodityID]
        channelModel?.reset()
        if let walletChannel = channelModel?.walletChannel {
            walletChannel.walletSymbolEqual = commodity.currency == STSPayAccount.current.payAccount.currency
            let off_money = commodity.coupon?.off_money ?? 0
            walletChannel.actualPayAmount = commodity.price.st_subtracting(decimal: off_money)
        }
        channelsSection?.commodityChannel = channelModel
        
        let channelCount = channelModel?.channels.count ?? 0
        let fheight = channelCount <= 1 ? 30.ui_scale : 64.ui_scale
        channelsSection?.footerSize = CGSize(width: STScreenWidth, height: fheight)
    } }
    
    // 选择过的商品是否有优惠券
    private var hadCoupon = false
    // 是否有价格计划 / 优惠券
    var isPromotion: Bool {
        let isMatchedCommodityPlan = selectedCommodity?.matched_commodity_plan != nil
        return hadCoupon || isMatchedCommodityPlan
    }
    
    // 当前商品
    private(set) var currentProduct: MemberProductDto?
    private var tipsSection: STCommodityMobileSectionModel?
    private(set) var channelsSection: STCommodityMobileSectionModel?
    
    private var sections: [STCommodityMobileSectionModel] = []
    
    private var allPayChannels: [String: PayChannelDto] = [:]
    private var commodityChannelDict: [String: MBCommodityChannelsModel] = [:]
    private var commodityCouponDict: [String: Coupon] = [:]
    
    private let lr = 16.ui_scale
    
    // MARK: - 其他逻辑
    private func clearModels() {
        tipsSection = nil
        channelsSection = nil
        selectedCommodity = nil
        sections = []
    }
    
    private var isLoading = false
    
    private let fprovider = STNetwork<MemberApi>()
    
    private func fitCommodity(_ commoditys: [MemberCommodityDto]) -> MemberCommodityDto? {
        var defaultCommodity = commoditys.first
        guard isFromCoupons else {
            return defaultCommodity
        }
        
        for commodity in commoditys {
            let commodityID = String(commodity.id)
            guard let _ = commodityCouponDict[commodityID] else { continue }
            defaultCommodity = commodity
            break
        }
        
        return defaultCommodity
    }
    
    func changedWalletAmount() {
        commodityChannelDict.forEach { (key, value) in
            value.updateWalletChannelInfo()
        }
    }
}

// MARK: - setup
extension STCommodityMobileViewModel {
    
    // MARK: - setup 商品规格详情
    private func setupCommodityDetail(product: MemberProductDto) {
        let name = product.name
        let commoditys = product.commoditys
        
        let section = STCommodityMobileSectionModel()
        sections.append(section)
        
        var type: STCommodityMobileSectionType = .commodity
        var cellSize = CGSize.zero
        var layoutEdgeinset = UIEdgeInsets.zero
        var footerSize = STDefaultCellSize
        var minimumLineSpacing = CGFloat.zero
        
        let commodity = fitCommodity(commoditys)
        setupCommodityTips(memberCommodity: commodity)
        setupCommodityChannel()
        // 获取tips Cell高度, 选中默认行, 支付渠道列表
        hadCoupon = false
        selectedCommodity = commodity
        
        switch product.product_type {
            // 捆绑
        case .dataFree:
            type = .commodityDataFree
            layoutEdgeinset = UIEdgeInsets(top: 0, left: lr, bottom: 16, right: lr)
            cellSize = CGSize(width: STScreenWidth-lr*2, height: 72)
            footerSize = CGSize(width: STScreenWidth, height: 8)
            minimumLineSpacing = 12
            // 独立内容包
        default:
            let specs = commodity?.specs_code
            if specs == .letValid { // 固定有效期
                type = .commodityDataSaveLetValid
                layoutEdgeinset = UIEdgeInsets(top: 0, left: lr, bottom: 0, right: lr)
                cellSize = CGSize(width: STScreenWidth-lr*2, height: 64)
                minimumLineSpacing = 12
            }
            else { // 添加 商品规格详情section   独立内容包
                type = .commodityDataSave
                cellSize = CGSize(width: STScreenWidth, height: 124)
            }
        }

        let productViewModel = MBProductViewModel(commodityList: commoditys, couponList: commodityCouponDict)
        section.productViewModel = productViewModel
        section.type = type
        section.title = name
        section.titleImageUrl = product.product_logo
        section.statisticCategroy = ds_categroy
        
        section.layoutEdgeinset = layoutEdgeinset
        section.cellSize = cellSize
        section.headerSize = CGSize(width: STScreenWidth, height: 52)
        section.footerSize = footerSize
        section.minimumLineSpacing = minimumLineSpacing
    }
    
    // MARK: - setup 商品规格说明
    private func setupCommodityTips(memberCommodity: MemberCommodityDto?) {
        guard let _ = memberCommodity else { return }
        
        let section = STCommodityMobileSectionModel()
        section.type = .commodityTips
        section.isImage = false
        section.statisticCategroy = ds_categroy
        section.commodityTips = MBCommodityDetailTipsModel()
        
        section.layoutEdgeinset = UIEdgeInsets(top: 8, left: lr, bottom: 0, right: lr)
        section.headerSize = STDefaultCellSize
        
        sections.append(section)
        tipsSection = section
    }
    
    // MARK: - setup 支付渠道
    private func setupCommodityChannel() {
        let section = STCommodityMobileSectionModel()
        section.statisticCategroy = ds_categroy
        section.type = .payChannel
        section.title = "membership_payment".localized()
        
        section.cellSize = CGSize(width: STScreenWidth, height: 47.ui_scale)
        section.headerSize = CGSize(width: STScreenWidth, height: 32.ui_scale)
        section.footerSize = CGSize(width: STScreenWidth, height: 64.ui_scale)
        
        sections.append(section)
        channelsSection = section
    }
    
    // MARK: - setup 当前商品 权益
    private func setupRights(product: MemberProductDto, rights: [MemberRightsDto]) {
        if rights.isEmpty { return }
        
        let section = STCommodityMobileSectionModel()
        section.type = .rights
        section.title = product.name + " " + OLLocalize("membership_right")
        section.productId = product.id
        
        section.layoutEdgeinset = UIEdgeInsets(top: 4, left: lr, bottom: 20, right: lr)
        section.minimumLineSpacing = 14.ui_scale
        section.minimumInteritemSpacing = 8.ui_scale
        
        let column = 4
        var width = 76.ui_scale
        let maxWidth = STScreenWidth - lr * 2
        let totalMargin = 24.ui_scale // (column - 1) * 8
        let totalWidth = width * CGFloat(column) + totalMargin
        if maxWidth < totalWidth {
            width = (maxWidth - totalMargin) / CGFloat(column)
        }
        let height =  110 / 76 * width
        section.cellSize = CGSize(width: width, height: height)
        section.headerSize = CGSize(width: STScreenWidth, height: 52)
        section.footerSize = CGSize(width: STScreenWidth, height: 8)
        
        section.rights = rights
        sections.append(section)
    }
    
    // MARK: - setup 推荐 商品
    private func setupRecommendCommodities(_ categories: [MemberCategoryDto], isDataBundle: Bool) {
        // 商品组
        var products = [MemberProductDto]()
        categories.forEach { category in
            category.products.forEach { product in
                products.append(product)
            }
        }
        if products.isEmpty { return }
        
        let section = STCommodityMobileSectionModel()
        section.type = .recommendProduct
        section.title = OLLocalize("membership_recommended")
        
        let bottom: CGFloat = isDataBundle ? 12 : 32
        section.layoutEdgeinset = UIEdgeInsets(top: 0, left:lr, bottom: bottom, right: lr)
        
        section.cellSize = CGSize(width: STScreenWidth-lr*2, height: 44.ui_scale)
        section.minimumLineSpacing = 12
        section.headerSize = CGSize(width: STScreenWidth, height: 52)
        section.footerSize = CGSize(width: STScreenWidth, height: 8)
        
        section.products = products
        sections.append(section)
    }
    
    // MARK: - setup 推荐 流量包
    private func setupRecommendBundleInfo(_ bundleInfo: DataBundleInfo) {
        
        guard !bundleInfo.carrier_name.isEmpty else { return }
        
        let bundleProduct = MemberProductDto()
        bundleProduct.product_logo = bundleInfo.icon
        bundleProduct.name = bundleInfo.description
        bundleProduct.id =  bundleInfo.carrierId
        bundleProduct.link = bundleInfo.link
        bundleProduct.isDataBundleInfo = true
        
        let section = STCommodityMobileSectionModel()
        section.isImage = false
        section.type = .recommendBundle
        
        section.minimumLineSpacing = 12
        section.headerSize = STDefaultCellSize
        section.footerSize = CGSize(width: STScreenWidth, height: 8)
        section.layoutEdgeinset = UIEdgeInsets(top: 0, left: lr, bottom: 32, right: lr)
        section.cellSize = CGSize(width: STScreenWidth-lr*2, height: 44.ui_scale)
        
        section.products = [bundleProduct]
        sections.append(section)
    }
    
    // 用户服务协议
    func setupService() {
        let section = STCommodityMobileSectionModel()
        section.type = .serviceAgreement
        section.isImage = false
        section.headerSize = STDefaultCellSize
        section.footerSize = STDefaultCellSize
        section.cellSize = CGSize(width: STScreenWidth, height: 52.ui_scale)
        
        sections.append(section)
    }
}

// MARK: - response 数据 2次处理
extension STCommodityMobileViewModel {
    
    // MARK: - response 当前商品 全部支付渠道
    private func rs_productAllChannel(_ payChannels: [PayChannelDto]) {
        var productAllChannel: [String: PayChannelDto] = [:]
        payChannels.forEach({ channel in
            let channelID = String(channel.id)
            productAllChannel[channelID] = channel
        })
        allPayChannels = productAllChannel
    }
    
    // 全部的商品规格对应的 支付渠道列表详情
    private func rs_commodityChannels(_ commodityChannels: [CommodityChannel]) {
        var channelDict = [String: MBCommodityChannelsModel]()
        var couponDict = [String: Coupon]()
        
        
        commodityChannels.forEach { commodity in
            // 商品规格对应的 支付渠道列表详情
            let id = commodity.commodityId
            let channelsModel = MBCommodityChannelsModel(commodityChannel: commodity, allPayChannels: allPayChannels)
            channelDict[id] = channelsModel
            guard let coupon = commodity.coupon else { return }
            couponDict[id] = coupon
        }
        commodityChannelDict = channelDict
        commodityCouponDict = couponDict
    }
    
    // 推荐 商品; 推荐 流量包
    private func rs_recommend(memberCategoryDto: [MemberCategoryDto],
                              dataBundleInfo: DataBundleInfo?) {
        // 推荐 商品
        let isDataBundle = dataBundleInfo != nil
        setupRecommendCommodities(memberCategoryDto, isDataBundle: isDataBundle)
        
        // 推荐 流量包
        guard let bundleInfo = dataBundleInfo else { return }
        setupRecommendBundleInfo(bundleInfo)
    }
}

// MARK: - response
extension STCommodityMobileViewModel {
    
    // MARK: - response 商品的渠道详情 优惠详情
    private func responseCommodityChannelInfo(_ info: ChannelDiscountInfo) {
        if let payChannels = info.payChannels {
            rs_productAllChannel(payChannels)
        }
        
        guard let commodityChannels = info.commoditys else { return }
        rs_commodityChannels(commodityChannels)
    }
    
    // MARK: - response 展示的商品规格详情
    /**
     *  product: 展示的商品
     *  memberCategoryDto: 推荐商品组
     *  dataBundleInfo: 合作流量包
     */
    public func responseMobileCommodityDetail(product: MemberProductDto,
                                              categories: [MemberCategoryDto]) {
        currentProduct = product
        clearModels()
        
        // 商品规格详情
        setupCommodityDetail(product: product)
        
        // 权益 数据
        let rights = product.rights
        setupRights(product:product, rights: rights)
        
        // 推荐商品数据
        rs_recommend(memberCategoryDto: categories, dataBundleInfo: dataBundleInfo)
        
        // 用户服务协议
        setupService()
    }
}

// MARK: - request
extension STCommodityMobileViewModel {
    
    //根据直播频道获取商品
    func requestProductOfChannel(id: Int, completion: (()->Void)? = nil) {
        if isLoading { return }
        isLoading = true
        fprovider.sendRequest(MemberApi.getProductOfChannel(channelID: id)) {[weak self] (result: STResult<MemberProductResponse, MoyaError>) in
            guard let strongSelf = self else { return }
            
            switch result {
            case .success(let value):
                strongSelf.selectedProduct = value.data.first?.products.first
            case .failure(_):
                break
            }
            strongSelf.isLoading = false
            completion?()
        }
    }
    
    // 根据点播频道获取商品
    func requestProductOfVod(id: Int, completion: (()->Void)? = nil) {
        if isLoading { return }
        isLoading = true
        fprovider.sendRequest(MemberApi.getProductOfVodId(vodID: id)) {[weak self] (result: STResult<MemberProductResponse, MoyaError>) in
            guard let strongSelf = self else { return }
            
            switch result {
            case .success(let value):
                strongSelf.selectedProduct = value.data.first?.products.first
            case .failure(_):
                break
            }
            strongSelf.isLoading = false
            completion?()
        }
    }
    
    // 根据优惠券获取商品
    func requestProductOfCoupon(id: Int, completion: (()->Void)? = nil) {
        if isLoading { return }
        isLoading = true
        fprovider.sendRequest(MemberApi.getProductOfCoupon(couponID: id)) {[weak self] (result: STResult<MemberProductResponse, MoyaError>) in
            guard let strongSelf = self else { return }
            
            switch result {
            case .success(let value):
                strongSelf.selectedProduct = value.data.first?.products.first
            case .failure(_):
                break
            }
            strongSelf.isLoading = false
            completion?()
        }
    }
    
    // 根据 商品模型 请求商品相关信息 = 商品推荐信息 + 权益信息
    // 就是 Mobile 下的展示信息
    func requestMobileCommodityDetail(product: MemberProductDto, couponInstanceID: String, utm: String, completion: ((_ isSuccess: Bool, _ sections: [STCommodityMobileSectionModel]) -> Void)? = nil) {
        if isLoading { return }
        isLoading = true
        let pid = product.id
        let target2 = MemberApi.preOrderInfo(productId: "\(pid)", couponInstanceID: couponInstanceID, utm: utm)
        fprovider.sendBatchResultObjectRequest(MemberApi.getProductOfRecommandProduct(productID: pid), target2: target2) { [weak self] (result: STResult<(MemberProductResponse, ChannelDiscountInfo), MoyaError>) in
            guard let strongSelf = self else { return }
            
            var success = false
            switch result {
            case .success(let value):
                // products: 当前商品(规格信息, 提示信息等)
                // categories: 推荐 商品
                let (productsResult, channelDiscountInfo) = value
                strongSelf.responseCommodityChannelInfo(channelDiscountInfo)
                strongSelf.responseMobileCommodityDetail(product: product, categories: productsResult.data)
                success = true
            case .failure(_):
                break
            }
            
            strongSelf.isLoading = false
            completion?(success, strongSelf.sections)
        }
    }
}

// MARK: - 报数
extension STCommodityMobileViewModel {
    
    /// "buy_show": 价钱更新
    /// "ProdBuy" : 点击buy
    // 底部购买按钮
    public func ds_buyDataStatistics(action: String) {
        guard let product = currentProduct, let commodity = selectedCommodity
        else { return  }
        
        let title = product.extend_status.string
        var msg: [String: Any] = commodity.dataStatistics
        msg["buy_status"] = title
        msg["total_amount"] = commodity.price
        
        let label = "\(product.name)_\(commodity.name)_\(title)"
        let event = DSEvent(category: ds_categroy, action: action, label: label, value: "\(commodity.price)")
        DataStatistics.sendEvent(event: event, msg: msg)
    }
    
    // 选择推荐 - 商品
    func ds_didTapRecommend(product: MemberProductDto) {
        
        let event = DSEvent(category: ds_categroy, action: "ProdTap", label: product.name, value: "1")
        DataStatistics.sendEvent(event: event, msg: product.dataStatistics)
    }
    
    // 选择商品 - 数据包
    func ds_didTapDataBundleInfo(id: String) {
        let event = DSEvent(category: ds_categroy, action: "dataplan_product_click", label: "", value: "1", lt: .event)
        DataStatistics.sendEvent(event: event, msg: ["dataplan_id": id])
    }
    
    // 选择商品 - 规格
    func ds_didTapCommodity(commodity: MemberCommodityDto) {
        let ext = [DSKExtension.channel_info.rawValue: commodity.channelInfo]
        let event = DSEvent(category: ds_categroy,
                            action: "commodity_select",
                            label: commodity.name, value: "1")
        DataStatistics.sendEvent(event: event, msg: ext)
    }
    
    // 订单成功后去支付
    func ds_orderPay(commodity: MemberCommodityDto) {
        let event = DSEvent(category: ds_categroy,
                            action: "OrderPay",
                            label: commodity.name, value: "1")
        DataStatistics.sendEvent(event: event)
    }
}
